package controllers

import (
	"github.com/jinzhu/gorm"
	jsoniter "github.com/json-iterator/go"
	"github.com/kataras/iris"
	"github.com/kataras/iris/mvc"
	"golang.org/x/crypto/bcrypt"
	"io/ioutil"
	"net/http"
	"time"
	"tizhi_front/model"
	"tizhi_front/nspel"
	"tizhi_front/request"
	"tizhi_front/response"
	"tizhi_front/utils"
)

type UserController struct {
	Ctx iris.Context
}

func (c *UserController) BeforeActivation(b mvc.BeforeActivation) {
	b.Handle("POST", "/id_name_login", "IdNameLogin")
	b.Handle("POST", "/school_roll_id_name_login", "SchoolRollIdNameLogin")
	b.Handle("POST", "/id_login", "IdLogin")
	b.Handle("POST", "/phone_login", "PhoneLogin")
	b.Handle("POST", "/user_score_info", "UserScoreInfo", beforeCommonToken)
	b.Handle("PUT", "/user_info", "UserInfoUpdate", beforeUserInfoUpdate)
	b.Handle("PUT", "/user_pass", "UpdatePass", beforeUpdatePass)
	b.Handle("POST", "/user_pass_reset_by_phone", "ResetPassByPhone")
	b.Handle("POST", "/user_pass_reset_by_id", "ResetPassById")
	b.Handle("POST", "/blind_phone", "BlindPhone", beforeBlindPhone)
	b.Handle("POST", "/wechat_login", "WechatLogin")
	b.Handle("POST", "/wechat_bind", "WechatBind")
	b.Handle("POST", "/avatar_list", "AvatarList", beforeCommonToken)
	b.Handle("POST", "/avatar_set/{id:long}", "AvatarSet", beforeCommonToken)
}

func beforeCommonToken(ctx iris.Context) {
	req := response.TokenInfo{}
	err := ctx.ReadJSON(&req)
	if err != nil {
		_, _ = ctx.JSON(response.InvalidParameters)
		return
	}
	if !utils.ValidateToken(&req) {
		ctx.StatusCode(403)
		_, _ = ctx.JSON(response.InvalidParameters)
		return
	}
	ctx.Values().Set("uid", req.Uid)
	ctx.Next()
}

func beforeUserInfoUpdate(ctx iris.Context) {
	req := request.UserInfoUpdate{}
	err := ctx.ReadJSON(&req)
	if err != nil {
		_, _ = ctx.JSON(response.InvalidParameters)
		return
	}
	if !utils.ValidateToken(&req.TokenInfo) {
		ctx.StatusCode(403)
		_, _ = ctx.JSON(response.InvalidParameters)
		return
	}
	ctx.Values().Set("uid", req.TokenInfo.Uid)
	ctx.Values().Set("data", req.UserInfo)
	ctx.Next()
}

func beforeUpdatePass(ctx iris.Context) {
	req := request.UpdatePass{}
	err := ctx.ReadJSON(&req)
	if err != nil {
		_, _ = ctx.JSON(response.InvalidParameters)
		return
	}
	if !utils.ValidateToken(&req.TokenInfo) {
		ctx.StatusCode(403)
		_, _ = ctx.JSON(response.InvalidParameters)
		return
	}
	ctx.Values().Set("uid", req.TokenInfo.Uid)
	ctx.Values().Set("originPass", req.OriginPass)
	ctx.Values().Set("newPass", req.NewPass)
	ctx.Next()
}

func beforeBlindPhone(ctx iris.Context) {
	req := request.BlindPhone{}
	err := ctx.ReadJSON(&req)
	if err != nil {
		_, _ = ctx.JSON(response.InvalidParameters)
		return
	}
	if !utils.ValidateToken(&req.TokenInfo) {
		ctx.StatusCode(403)
		_, _ = ctx.JSON(response.InvalidParameters)
		return
	}
	ctx.Values().Set("uid", req.TokenInfo.Uid)
	ctx.Values().Set("phone", req.Phone)
	ctx.Values().Set("validCode", req.ValidCode)
	ctx.Next()
}

// @Title Id Name Login
// @Description 通过身份证号姓名登陆
// @Tags user
// @Param body body request.IdNameLogin true " "
// @Success 0 {object} response.TokenInfo "请求成功"
// @Failure 1 {string} string "请求无效"
// @Failure 2 {string} string "服务器运行错误"
// @Failure 3 {string} string "身份证号不存在"
// @Failure 4 {string} string "身份证号和姓名不匹配"
// @router /user/id_name_login [post]
func (c *UserController) IdNameLogin() response.JsonResponse {
	req := request.IdNameLogin{}
	err := c.Ctx.ReadJSON(&req)
	if err != nil {
		return response.InvalidParameters
	}
	if !req.Validate() {
		return response.InvalidParameters
	}
	student := model.Student0{}
	err = student.SelectByIdentityId(req.IdentityId)
	if err == gorm.ErrRecordNotFound {
		return response.JsonResponse{
			ErrCode: 3,
			ErrInfo: "身份证号不存在",
			Data:    "",
		}
	} else if err != nil {
		nspel.Error(err)
		return response.InternalServerError(err)
	}
	if student.Name != req.Name {
		return response.JsonResponse{
			ErrCode: 4,
			ErrInfo: "身份证号和姓名不匹配",
			Data:    "",
		}
	}
	token, err := utils.SignToken(student.Id)
	if err != nil {
		nspel.Error(err)
		return response.InternalServerError(err)
	}
	return response.JsonResponse{
		ErrCode: 0,
		ErrInfo: "",
		Data: response.TokenInfo{
			Token: token,
			Uid:   student.Id,
		},
	}
}

// @Title Id Name Login
// @Description 通过学籍号姓名登陆
// @Tags user
// @Param body body request.SchoolRollIdNameLogin true " "
// @Success 0 {object} response.TokenInfo "请求成功"
// @Failure 1 {string} string "请求无效"
// @Failure 2 {string} string "服务器运行错误"
// @Failure 3 {string} string "学籍号不存在"
// @Failure 4 {string} string "学籍号和姓名不匹配"
// @router /user/school_roll_id_name_login [post]
func (c *UserController) SchoolRollIdNameLogin() response.JsonResponse {
	req := request.SchoolRollIdNameLogin{}
	err := c.Ctx.ReadJSON(&req)
	if err != nil {
		return response.InvalidParameters
	}
	if !req.Validate() {
		return response.InvalidParameters
	}
	student := model.Student1{}
	err = student.SelectBySchoolRollId(req.SchoolRollId)
	if err == gorm.ErrRecordNotFound {
		return response.JsonResponse{
			ErrCode: 3,
			ErrInfo: "学籍号不存在",
			Data:    "",
		}
	} else if err != nil {
		nspel.Error(err)
		return response.InternalServerError(err)
	}
	if student.Name != req.Name {
		return response.JsonResponse{
			ErrCode: 4,
			ErrInfo: "学籍号和姓名不匹配",
			Data:    "",
		}
	}
	token, err := utils.SignToken(student.Id)
	if err != nil {
		nspel.Error(err)
		return response.InternalServerError(err)
	}
	return response.JsonResponse{
		ErrCode: 0,
		ErrInfo: "",
		Data: response.TokenInfo{
			Token: token,
			Uid:   student.Id,
		},
	}
}

// @Title IdLogin
// @Description 使用学生Id登录
// @Tags user
// @Param	body body request.IdLogin true " "
// @Success 0	{object} response.TokenInfo "请求成功"
// @Failure 1 {string} string "请求无效"
// @Failure 2 {string} string "服务器运行错误"
// @Failure 3 {string} string "学籍号不存在"
// @Failure 4 {string} string "用户名密码错误"
// @router /user/id_login [post]
func (c *UserController) IdLogin() response.JsonResponse {
	req := request.IdLogin{}
	err := c.Ctx.ReadJSON(&req)
	if err != nil {
		return response.InvalidParameters
	}
	if !req.Validate() {
		return response.InvalidParameters
	}
	student := model.Student2{}
	err = student.SelectBySchoolRollId(req.StudentId)
	if err == gorm.ErrRecordNotFound {
		return response.JsonResponse{
			ErrCode: 3,
			ErrInfo: "学籍号不存在",
			Data:    "",
		}
	} else if err != nil {
		return response.InternalServerError(err)
	}
	err = bcrypt.CompareHashAndPassword([]byte(student.Password), []byte(req.Password))
	if err == bcrypt.ErrMismatchedHashAndPassword {
		return response.JsonResponse{
			ErrCode: 4,
			ErrInfo: "用户名密码错误",
			Data:    "",
		}
	} else if err != nil {
		nspel.Error(err)
		return response.InternalServerError(err)
	}
	token, err := utils.SignToken(student.Id)
	if err != nil {
		nspel.Error(err)
		return response.InternalServerError(err)
	}
	return response.JsonResponse{
		ErrCode: 0,
		ErrInfo: "",
		Data: response.TokenInfo{
			Token: token,
			Uid:   student.Id,
		},
	}
}

// @Title PhoneLogin
// @Description 使用手机号登录
// @Tags user
// @Param	body body request.PhoneLogin true " "
// @Success 0	{object} response.TokenInfo "请求成功"
// @Failure 1 {string} string "请求无效"
// @Failure 2 {string} string "服务器运行错误"
// @Failure 3 {string} string "手机号不存在"
// @Failure 4 {string} string "用户名密码错误"
// @router /user/phone_login [post]
func (c *UserController) PhoneLogin() response.JsonResponse {
	req := request.PhoneLogin{}
	err := c.Ctx.ReadJSON(&req)
	if err != nil {
		return response.InvalidParameters
	}
	if !req.Validate() {
		return response.InvalidParameters
	}
	student := model.Student3{}
	err = student.SelectByPhone(req.Phone)
	if err == gorm.ErrRecordNotFound {
		return response.JsonResponse{
			ErrCode: 3,
			ErrInfo: "手机号不存在",
			Data:    "",
		}
	} else if err != nil {
		return response.InternalServerError(err)
	}
	err = bcrypt.CompareHashAndPassword([]byte(student.Password), []byte(req.Password))
	if err == bcrypt.ErrMismatchedHashAndPassword {
		return response.JsonResponse{
			ErrCode: 4,
			ErrInfo: "用户名密码错误",
			Data:    "",
		}
	} else if err != nil {
		nspel.Error(err)
		return response.InternalServerError(err)
	}
	token, err := utils.SignToken(student.Id)
	if err != nil {
		nspel.Error(err)
		return response.InternalServerError(err)
	}
	return response.JsonResponse{
		ErrCode: 0,
		ErrInfo: "",
		Data: response.TokenInfo{
			Token: token,
			Uid:   student.Id,
		},
	}
}

// @Title UserScoreInfo
// @Description 获取所有用户相关的信息（包含测试成绩）
// @Tags user
// @Param	body body response.TokenInfo	true " "
// @Success 0	{object} response.UserScoreInfo
// @Failure 1 {string} string "用户未登录或者登陆已过期"
// @Failure 2 {string} string "系统错误，获取失败，具体error信息为系统报错信息"
// @router /user/user_score_info [post]
func (c *UserController) UserScoreInfo() response.JsonResponse {
	uid, err := c.Ctx.Values().GetInt64("uid")
	if err != nil {
		nspel.Error(err)
		return response.JsonResponse{
			ErrCode: 2,
			ErrInfo: err.Error(),
			Data:    "",
		}
	}
	userScoreInfo, err := utils.GetUserScoreInfo(uid)
	if err != nil {
		nspel.Error(err)
		return response.JsonResponse{
			ErrCode: 2,
			ErrInfo: err.Error(),
			Data:    "",
		}
	}
	return response.JsonResponse{
		ErrCode: 0,
		ErrInfo: "",
		Data:    userScoreInfo,
	}
}

// @Title UserInfo Update
// @Description 更新用户的基本信息
// @Tags user
// @Param	body body request.UserInfoUpdate true " "
// @Success 0	{object} response.JsonResponse
// @Failure 1 {string} string "用户未登录或者登陆已过期"
// @Failure 2 {string} string "系统错误，获取失败，具体error信息为系统报错信息"
// @router /user/user_info [put]
func (c *UserController) UserInfoUpdate() response.JsonResponse {
	uid, err := c.Ctx.Values().GetInt64("uid")
	if err != nil {
		nspel.Error(err)
		return response.JsonResponse{
			ErrCode: 2,
			ErrInfo: err.Error(),
			Data:    "",
		}
	}
	data := c.Ctx.Values().Get("data").(response.UserInfo)
	if !data.Validate() {
		return response.InvalidParameters
	}
	birth, _ := time.Parse("2006-01-02", data.Birth)
	sex, err := utils.SexStob(data.Gender)
	if err != nil {
		nspel.Error(err)
		return response.JsonResponse{
			ErrCode: 2,
			ErrInfo: err.Error(),
			Data:    "",
		}
	}
	student := model.Student5{
		PicUrl:   data.PicUrl,
		NickName: data.NickName,
		Sex:      sex,
		Birthday: birth,
		Height:   float64(data.Height),
		Weight:   float64(data.Weight),
	}
	err = student.UpdateById(uid)
	if err != nil {
		nspel.Error(err)
		return response.JsonResponse{
			ErrCode: 2,
			ErrInfo: err.Error(),
			Data:    "",
		}
	}
	utils.NewMessage(uid, "修改个人信息成功")
	return response.JsonResponse{
		ErrCode: 0,
		ErrInfo: "",
		Data:    "",
	}
}

// @Title UserPass Update
// @Description 更新用户密码
// @Tags user
// @Param	body body request.UpdatePass	true " "
// @Success 0	{object} response.JsonResponse
// @Failure 1 {string} string "用户未登录或者登陆已过期"
// @Failure 2 {string} string "系统错误，获取失败，具体error信息为系统报错信息"
// @router /user/user_pass [put]
func (c *UserController) UpdatePass() response.JsonResponse {
	uid, err := c.Ctx.Values().GetInt64("uid")
	if err != nil {
		nspel.Error(err)
		return response.JsonResponse{
			ErrCode: 2,
			ErrInfo: err.Error(),
			Data:    "",
		}
	}
	originPass := c.Ctx.Values().GetString("originPass")
	if len(originPass) == 0 {
		return response.InvalidParameters
	}
	newPass := c.Ctx.Values().GetString("newPass")
	if len(newPass) == 0 {
		return response.InvalidParameters
	}
	student := model.Student6{}
	err = student.SelectById(uid)
	if err != nil {
		nspel.Error(err)
		return response.JsonResponse{
			ErrCode: 2,
			ErrInfo: err.Error(),
			Data:    "",
		}
	}
	err = bcrypt.CompareHashAndPassword([]byte(student.Password), []byte(originPass))
	if err == bcrypt.ErrMismatchedHashAndPassword {
		return response.InvalidParameters
	} else if err != nil {
		nspel.Error(err)
		return response.JsonResponse{
			ErrCode: 2,
			ErrInfo: err.Error(),
			Data:    "",
		}
	}
	password, err := bcrypt.GenerateFromPassword([]byte(newPass), bcrypt.MinCost)
	if err != nil {
		nspel.Error(err)
		return response.JsonResponse{
			ErrCode: 2,
			ErrInfo: err.Error(),
			Data:    "",
		}
	}
	student.Password = string(password)
	err = student.UpdateById(uid)
	if err != nil {
		nspel.Error(err)
		return response.JsonResponse{
			ErrCode: 2,
			ErrInfo: err.Error(),
			Data:    "",
		}
	}
	utils.NewMessage(uid, "修改密码成功")
	return response.JsonResponse{
		ErrCode: 0,
		ErrInfo: "",
		Data:    "",
	}
}

// @Title UserPass Reset
// @Description 通过验证码重置用户密码
// @Tags user
// @Param	body body request.ResetPassByPhone true " "
// @Success 0	{object} response.JsonResponse
// @Failure 1 {string} string "用户手机号不存在"
// @Failure 2 {string} string "系统错误，获取失败，具体error信息为系统报错信息"
// @router /user/user_pass_reset_by_phone [post]
func (c *UserController) ResetPassByPhone() response.JsonResponse {
	req := request.ResetPassByPhone{}
	err := c.Ctx.ReadJSON(&req)
	if err != nil {
		return response.InvalidParameters
	}
	if !req.Validate() {
		return response.InvalidParameters
	}
	phone := utils.Phone{
		Phone: req.Phone,
	}
	ok, err := phone.ValidCode(req.ValidCode, 1)
	if err != nil {
		nspel.Error(err)
		return response.JsonResponse{
			ErrCode: 2,
			ErrInfo: err.Error(),
			Data:    "",
		}
	}
	if !ok {
		return response.InvalidParameters
	}
	student := model.Student8{}
	err = student.SelectByPhone(req.Phone)
	if err == gorm.ErrRecordNotFound {
		return response.InvalidParameters
	} else if err != nil {
		nspel.Error(err)
		return response.JsonResponse{
			ErrCode: 2,
			ErrInfo: err.Error(),
			Data:    "",
		}
	}
	password, err := bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.MinCost)
	studentP := model.Student6{Password: string(password)}
	err = studentP.UpdateById(student.Id)
	if err != nil {
		nspel.Error(err)
		return response.JsonResponse{
			ErrCode: 2,
			ErrInfo: err.Error(),
			Data:    "",
		}
	}
	utils.NewMessage(student.Id, "修改密码成功")
	return response.JsonResponse{
		ErrCode: 0,
		ErrInfo: "",
		Data:    "",
	}
}

// @Title UserPass Reset
// @Description 通过用户原始信息（教育Id、身份证号码、姓名）重置用户密码
// @Tags user
// @Param	body body request.ResetPassById	true " "
// @Success 0	{object} response.JsonResponse
// @Failure 1 {string} string "信息匹配错误"
// @Failure 2 {string} string "系统错误，获取失败，具体error信息为系统报错信息"
// @router /user/user_pass_reset_by_id [post]
func (c *UserController) ResetPassById() response.JsonResponse {
	req := request.ResetPassById{}
	err := c.Ctx.ReadJSON(&req)
	if err != nil {
		return response.InvalidParameters
	}
	if !req.Validate() {
		return response.InvalidParameters
	}
	student := model.Student0{}
	err = student.SelectBySchoolRollId(req.StudentId)
	if err == gorm.ErrRecordNotFound {
		return response.InvalidParameters
	} else if err != nil {
		nspel.Error(err)
		return response.JsonResponse{
			ErrCode: 2,
			ErrInfo: err.Error(),
			Data:    "",
		}
	}
	if student.Name != req.StudentName || (len(student.IdentityId) != 0 && student.IdentityId != req.IdNumber) {
		return response.InvalidParameters
	}
	password, err := bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.MinCost)
	if err != nil {
		nspel.Error(err)
		return response.JsonResponse{
			ErrCode: 2,
			ErrInfo: err.Error(),
			Data:    "",
		}
	}
	studentP := model.Student6{Password: string(password)}
	err = studentP.UpdateById(student.Id)
	if err != nil {
		nspel.Error(err)
		return response.JsonResponse{
			ErrCode: 2,
			ErrInfo: err.Error(),
			Data:    "",
		}
	}
	utils.NewMessage(student.Id, "修改密码成功")
	return response.JsonResponse{
		ErrCode: 0,
		ErrInfo: "",
		Data:    "",
	}
}

// @Title UserPhone Blind
// @Description 手机号码绑定
// @Tags user
// @Param	body body request.BlindPhone	true " "
// @Success 0	{object} response.JsonResponse
// @Failure 1 {string} string "信息匹配错误"
// @Failure 2 {string} string "系统错误，获取失败，具体error信息为系统报错信息"
// @router /user/blind_phone [post]
func (c *UserController) BlindPhone() response.JsonResponse {
	uid, err := c.Ctx.Values().GetInt64("uid")
	if err != nil {
		nspel.Error(err)
		return response.JsonResponse{
			ErrCode: 2,
			ErrInfo: err.Error(),
			Data:    "",
		}
	}
	phone := c.Ctx.Values().GetString("phone")
	validCode := c.Ctx.Values().GetString("validCode")
	phoneTool := utils.Phone{Phone: phone}
	ok, err := phoneTool.ValidCode(validCode, 0)
	if err != nil {
		nspel.Error(err)
		return response.JsonResponse{
			ErrCode: 2,
			ErrInfo: err.Error(),
			Data:    "",
		}
	}
	if !ok {
		return response.InvalidParameters
	}
	student := model.StudentE{}
	err = student.UpdatePhoneById(uid, phone)
	if err != nil {
		nspel.Error(err)
		return response.JsonResponse{
			ErrCode: 2,
			ErrInfo: err.Error(),
			Data:    "",
		}
	}
	utils.NewMessage(uid, "绑定手机号成功")
	return response.JsonResponse{
		ErrCode: 0,
		ErrInfo: "",
		Data:    "",
	}
}

// Title Wechat Login
// Description 微信登陆
// Tags user
// Param body body request.WechatLogin true " "
// Success 0 {object} response.TokenInfo "请求成功"
// Failure 1 {string} string "信息匹配错误"
// Failure 2 {string} string "系统错误，获取失败，具体error信息为系统报错信息"
// Failure 3 {string} string "未绑定用户"
// router /user/wechat_login [post]
func (c *UserController) WechatLogin() response.JsonResponse {
	req := request.WechatLogin{}
	err := c.Ctx.ReadJSON(&req)
	if err != nil {
		return response.JsonResponse{
			ErrCode: 1,
			ErrInfo: "请求无效",
			Data:    "",
		}
	}
	wechatConfig := nspel.GetWechatConfig()
	resp, err := http.Get("https://api.weixin.qq.com/sns/jscode2session?appid=" + wechatConfig.AppId + "&secret=" + wechatConfig.AppSecret + "&js_code=" + req.Code + "&grant_type=authorization_code")
	if err != nil {
		_ = resp.Body.Close()
		nspel.Error(err)
		return response.JsonResponse{
			ErrCode: 2,
			ErrInfo: err.Error(),
			Data:    "",
		}
	}
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		_ = resp.Body.Close()
		nspel.Error(err)
		return response.JsonResponse{
			ErrCode: 2,
			ErrInfo: err.Error(),
			Data:    "",
		}
	}
	_ = resp.Body.Close()
	var json = jsoniter.ConfigCompatibleWithStandardLibrary
	resCode := response.WechatAuthCode{}
	err = json.Unmarshal(body, &resCode)
	if err != nil {
		_ = resp.Body.Close()
		nspel.Error(err)
		return response.JsonResponse{
			ErrCode: 2,
			ErrInfo: err.Error(),
			Data:    "",
		}
	}
	if resCode.ErrCode != 0 {
		return response.JsonResponse{
			ErrCode: 2,
			ErrInfo: "请求错误",
			Data:    resCode,
		}
	}
	student := model.Student8{}
	err = student.SelectByWechatOpenId(resCode.OpenId)
	if err == gorm.ErrRecordNotFound {
		return response.JsonResponse{
			ErrCode: 3,
			ErrInfo: "未绑定用户",
			Data:    "",
		}
	} else if err != nil {
		nspel.Error(err)
		return response.JsonResponse{
			ErrCode: 2,
			ErrInfo: err.Error(),
			Data:    "",
		}
	}
	token, err := utils.SignToken(student.Id)
	if err != nil {
		nspel.Error(err)
		return response.JsonResponse{
			ErrCode: 2,
			ErrInfo: err.Error(),
			Data:    "",
		}
	}
	return response.JsonResponse{
		ErrCode: 0,
		ErrInfo: "",
		Data: response.TokenInfo{
			Token: token,
			Uid:   student.Id,
		},
	}
}

// Title Wechat Bind
// Description 微信绑定
// Tags user
// Param body body request.WechatBind true " "
// Success 0 {object} response.TokenInfo "请求成功"
// Failure 1 {string} string "信息匹配错误"
// Failure 2 {string} string "系统错误，获取失败，具体error信息为系统报错信息"
// Failure 3 {string} string "学籍号不存在"
// Failure 4 {string} string "学籍号密码不匹配"
// Failure 5 {string} string "该用户已经绑定其他微信"
// router /user/wechat_bind [post]
func (c *UserController) WechatBind() response.JsonResponse {
	req := request.WechatBind{}
	err := c.Ctx.ReadJSON(&req)
	if err != nil {
		return response.JsonResponse{
			ErrCode: 1,
			ErrInfo: "请求无效",
			Data:    "",
		}
	}
	wechatConfig := nspel.GetWechatConfig()
	resp, err := http.Get("https://api.weixin.qq.com/sns/jscode2session?appid=" + wechatConfig.AppId + "&secret=" + wechatConfig.AppSecret + "&js_code=" + req.Code + "&grant_type=authorization_code")
	if err != nil {
		_ = resp.Body.Close()
		nspel.Error(err)
		return response.JsonResponse{
			ErrCode: 2,
			ErrInfo: err.Error(),
			Data:    "",
		}
	}
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		_ = resp.Body.Close()
		nspel.Error(err)
		return response.JsonResponse{
			ErrCode: 2,
			ErrInfo: err.Error(),
			Data:    "",
		}
	}
	_ = resp.Body.Close()
	var json = jsoniter.ConfigCompatibleWithStandardLibrary
	resCode := response.WechatAuthCode{}
	err = json.Unmarshal(body, &resCode)
	if err != nil {
		_ = resp.Body.Close()
		nspel.Error(err)
		return response.JsonResponse{
			ErrCode: 2,
			ErrInfo: err.Error(),
			Data:    "",
		}
	}
	if resCode.ErrCode != 0 {
		return response.JsonResponse{
			ErrCode: 2,
			ErrInfo: "请求错误",
			Data:    resCode,
		}
	}
	student := model.Student8{}
	err = student.SelectByWechatOpenId(resCode.OpenId)
	if err != nil && err != gorm.ErrRecordNotFound {
		nspel.Error(err)
		return response.JsonResponse{
			ErrCode: 2,
			ErrInfo: err.Error(),
			Data:    "",
		}
	} else if err == nil {
		token, err := utils.SignToken(student.Id)
		if err != nil {
			nspel.Error(err)
			return response.JsonResponse{
				ErrCode: 2,
				ErrInfo: err.Error(),
				Data:    "",
			}
		}
		return response.JsonResponse{
			ErrCode: 0,
			ErrInfo: "",
			Data: response.TokenInfo{
				Token: token,
				Uid:   student.Id,
			},
		}
	}
	student10 := model.Student10{}
	err = student10.SelectBySchoolRollId(req.StudentId)
	if err == gorm.ErrRecordNotFound {
		return response.JsonResponse{
			ErrCode: 3,
			ErrInfo: "学籍号不存在",
			Data:    "",
		}
	} else if err != nil {
		nspel.Error(err)
		return response.JsonResponse{
			ErrCode: 2,
			ErrInfo: err.Error(),
			Data:    "",
		}
	}
	err = bcrypt.CompareHashAndPassword([]byte(student10.Password), []byte(req.Password))
	if err == bcrypt.ErrMismatchedHashAndPassword {
		return response.JsonResponse{
			ErrCode: 4,
			ErrInfo: "学籍号密码不匹配",
			Data:    "",
		}
	} else if err != nil {
		nspel.Error(err)
		return response.JsonResponse{
			ErrCode: 2,
			ErrInfo: err.Error(),
			Data:    "",
		}
	}
	if len(student10.WechatOpenId) != 0 {
		return response.JsonResponse{
			ErrCode: 5,
			ErrInfo: "该用户已经绑定其他微信",
			Data:    "",
		}
	}
	err = student10.UpdateWechatOpenIdBySchoolRollId(req.StudentId, resCode.OpenId)
	if err != nil {
		nspel.Error(err)
		return response.JsonResponse{
			ErrCode: 2,
			ErrInfo: err.Error(),
			Data:    "",
		}
	}
	err = student.SelectBySchoolRollId(req.StudentId)
	if err != nil {
		nspel.Error(err)
		return response.JsonResponse{
			ErrCode: 2,
			ErrInfo: err.Error(),
			Data:    "",
		}
	}
	token, err := utils.SignToken(student.Id)
	if err != nil {
		nspel.Error(err)
		return response.JsonResponse{
			ErrCode: 2,
			ErrInfo: err.Error(),
			Data:    "",
		}
	}
	return response.JsonResponse{
		ErrCode: 0,
		ErrInfo: "",
		Data: response.TokenInfo{
			Token: token,
			Uid:   student.Id,
		},
	}
}

// @Title Avatar List
// @Description 获取头像列表
// @Tags user
// @Param	body body response.TokenInfo true "token"
// @Success 0 {object} response.AvatarList "请求成功"
// @Failure 1 {string} string "用户未登录或者登陆已过期"
// @Failure 2 {string} string "系统错误，获取失败，具体error信息为系统报错信息"
// @router /user/avatar_list [post]
func (c *UserController) AvatarList() response.JsonResponse {
	avatar := model.AvatarE{}
	avatars, err := avatar.SelectAll()
	if err != nil {
		nspel.Error(err)
		return response.JsonResponse{
			ErrCode: 2,
			ErrInfo: err.Error(),
			Data:    "",
		}
	}
	res := response.AvatarList{}
	res.AvatarList = make([]response.AvatarListInfo, len(avatars))
	for i := 0; i < len(avatars); i++ {
		res.AvatarList[i] = response.AvatarListInfo{
			Id:     avatars[i].Id,
			PicUrl: avatars[i].PicUrl,
		}
	}
	return response.JsonResponse{
		ErrCode: 0,
		ErrInfo: "",
		Data:    res,
	}
}

// @Title Avatar Set
// @Description 设置头像
// @Tags user
// @Param	id path int64	true "id for avatar"
// @Param	body body response.TokenInfo true "token"
// @Success 0 {object} response.JsonResponse "请求成功"
// @Failure 1 {string} string "用户未登录或者登陆已过期"
// @Failure 2 {string} string "系统错误，获取失败，具体error信息为系统报错信息"
// @router /user/avatar_set/{id} [post]
func (c *UserController) AvatarSet(id int64) response.JsonResponse {
	uid, err := c.Ctx.Values().GetInt64("uid")
	if err != nil {
		nspel.Error(err)
		return response.JsonResponse{
			ErrCode: 2,
			ErrInfo: err.Error(),
			Data:    "",
		}
	}
	avatar := model.Avatar0{}
	err = avatar.SelectById(id)
	if err == gorm.ErrRecordNotFound {
		return response.JsonResponse{
			ErrCode: 1,
			ErrInfo: "请求无效",
			Data:    "",
		}
	} else if err != nil {
		nspel.Error(err)
		return response.JsonResponse{
			ErrCode: 2,
			ErrInfo: err.Error(),
			Data:    "",
		}
	}
	student := model.StudentE{}
	err = student.UpdatePicUrlById(uid, avatar.PicUrl)
	if err != nil {
		nspel.Error(err)
		return response.JsonResponse{
			ErrCode: 2,
			ErrInfo: err.Error(),
			Data:    "",
		}
	}
	return response.JsonResponse{
		ErrCode: 0,
		ErrInfo: "",
		Data:    "",
	}
}
